// main.go
package main

import (
	"encoding/base64"
	//"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"
)

type myInfo struct {
	User, Pwd, Host, Domain, UrlPath string
}

var myIP, getIp string

func init() {
	myIP = getMyIP()
}

func main() {

	myinfo := new(myInfo)
	myinfo.User = ""
	myinfo.Pwd = ""
	myinfo.Host = "ddns.oray.com"
	myinfo.Domain = "7y2.vicp.net,moqiruyi.eicp.net"
	myinfo.UrlPath = "ph/update?hostname=%s&myip=%s"
	//myinfo.UrlPath := "dyndns/update?hostname=%s&myip=%s&wildcard=ON"
	ddnsName := []string{"花生壳(Oray)", "公云(3322)"}
	pubyun := []string{"yum.2288.org", "cnphpbb.2288.org"}
	for {
		getIp = getMyIP()
		if getIp == "127.0.0.1" {
			log.Println("网络断开,请等待...")
			break
		}
		if getIp != myIP {
			log.Println("getIp::", getIp)
			for _, vv := range ddnsName {
				log.Println("请等待" + vv + "处理结果...")
				if vv == "公云(3322)" {
					myinfo.Host = "members.3322.net"
					myinfo.UrlPath = "dyndns/update?hostname=%s&myip=%s&wildcard=ON"
					for _, myinfo.Domain = range pubyun {
						reqestDdns(myinfo)
					}
				} else {
					myinfo.Host = "ddns.oray.com"
					myinfo.UrlPath = "ph/update?hostname=%s&myip=%s"
					myinfo.Domain = "7y2.vicp.net,moqiruyi.eicp.net"
					reqestDdns(myinfo)
				}
			}
			myIP = getIp
		} else {
			log.Println("IP地址没有变化...")
		}
		time.Sleep(1000 * 60 * time.Millisecond)
	}
}

func reqestDdns(myinfo *myInfo) {
	//生成httpUrl
	httpUrl := "http://" + myinfo.Host + "/" + fmt.Sprintf(myinfo.UrlPath, myinfo.Domain, getIp)
	//base64加密
	data := []byte(myinfo.User + ":" + myinfo.Pwd)
	authorization := base64.StdEncoding.EncodeToString(data)
	//感谢unphp 提供防止HTTP请求超时的代码
	client := &http.Client{
		Transport: &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				deadline := time.Now().Add(10 * time.Second)
				c, err := net.DialTimeout(netw, addr, time.Second*10)
				if err != nil {
					return nil, err
				}
				c.SetDeadline(deadline)
				return c, nil
			},
		},
	}
	reqest, err := http.NewRequest("GET", httpUrl, nil)
	if err != nil {
		fmt.Println("Fatal error ", err.Error())
		os.Exit(0)
	}
	reqest.Header.Add("Host", myinfo.Host)
	reqest.Header.Add("Authorization", "Basic "+authorization)
	reqest.Header.Add("User-Agent", "shop-yun.go/v1.0")
	response, err := client.Do(reqest)

	if err != nil {
		fmt.Println("Fatal error ", err.Error())
		os.Exit(0)
	}
	defer response.Body.Close()

	if response.StatusCode == 200 {
		body, _ := ioutil.ReadAll(response.Body)
		bodystr := string(body)

		fmt.Println(getMsgCode(bodystr))
	}
}

//通过ddns.oray.com提供的URL得到外网IP
func getMyIP() string {
	var rStr string
	response, err := http.Get("http://ddns.oray.com/checkip")
	if err != nil {
		return "127.0.0.1"
	}
	//defer response.Body.Close()
	body, _ := ioutil.ReadAll(response.Body)
	bodystr := string(body)
	re, _ := regexp.Compile(`<body>(.*)<\/body>`)
	strs := re.FindStringSubmatch(bodystr)
	if len(strs) > 1 {
		str := strings.Split(strs[1], ": ")
		if len(str) > 1 {
			rStr = strings.TrimSpace(str[1])
		}
	}
	return rStr
}

//解析放回的code代码值
func getMsgCode(str string) string {
	var rStr string
	rStr = "%s %s"
	bodyStr := strings.Split(str, " ")

	switch bodyStr[0] {
	case "good":
		rStr = fmt.Sprintf(rStr, "["+bodyStr[0]+"] 更新成功", "--"+bodyStr[1])
	case "nochg":
		rStr = fmt.Sprintf(rStr, "["+bodyStr[0]+"] 更新成功,但没有改变IP", "--"+bodyStr[1])
	case "notfqdn":
		rStr = fmt.Sprintf(rStr, "["+bodyStr[0]+"] 未有激活花生壳的域名", "")
	case "nohost":
		rStr = fmt.Sprintf(rStr, "["+bodyStr[0]+"] 域名不存在或未激活花生壳", "")
	case "abuse":
		rStr = fmt.Sprintf(rStr, "["+bodyStr[0]+"] 请求失败，频繁请求或验证失败", "")
	case "!donator":
		rStr = fmt.Sprintf(rStr, "["+bodyStr[0]+"] 此功能需要付费用户才能使用", "")
	default:
		rStr = fmt.Sprintf(rStr, "系统错误", "")
	}
	return rStr
}
